/**
 * 
 */
package IC.Analyzer;

import java.util.EnumSet;

import IC.AST.ASTNode;
import IC.AST.nodes.*;
import IC.Analyzer.Types.*;
import IC.asm.operands.RegOperand;

/**
 *
 */
public class SymTabEntry {

	public enum IdKind {
		CLASS,
		LOCALVAR,
		FORMALPARAM,
		VIRTUALMETHOD,
		STATICMETHOD,
		MEMBERVAR,
		RETURNTYPE,
		THIS;

		public static EnumSet<IdKind> VarSet = 
			EnumSet.of(
					IdKind.LOCALVAR, 
					IdKind.FORMALPARAM, 
					IdKind.MEMBERVAR );

		public static EnumSet<IdKind> MethodSet = 
			EnumSet.of(
					IdKind.VIRTUALMETHOD, 
					IdKind.STATICMETHOD);

	}

	private ASTNode 		declNode;
	private Type 			type;
	private IdKind			kind;
	private	int				depth;
	private int				offset=1;
	private RegOperand		reg;
	
	
	/**
	 * @return the reg
	 */
	public RegOperand getReg() {
		return reg;
	}


	/**
	 * @param reg the reg to set
	 */
	public void setReg(RegOperand reg) {
		this.reg = reg;
	}


	/**
	 * @return the offset
	 */
	public int getOffset() {
		assert((offset % 4) == 0);
		return offset;
	}


	/**
	 * @param offset the offset to set
	 */
	public void setOffset(int offset) {
		assert((offset % 4) == 0);
		this.offset = offset;
	}


	/**
	 * @return the depth
	 */
	public int getDepth() {
		return depth;
	}

	
	/**
	 * @param depth the depth to set
	 */
	public void setDepth(int depth) {
		this.depth = depth;
	}
	
	
	/**
	 * make a new entry
	 * @param declNode the node where the symbol was declared
	 * @param type the symbol type
	 */
	public SymTabEntry(ASTNode declNode, Type type, IdKind kind) {
		this.declNode = declNode;
		this.type = type;
		this.kind = kind;
	}


	public SymTabEntry(ClassDecl declNode, ClassType classType) {
		this.declNode = declNode;
		this.type = classType;
		this.kind = IdKind.CLASS;
	}


	public SymTabEntry(MethodDecl declNode, MethodType type) {
		this.declNode = declNode;
		this.type = type;
		this.kind = declNode.isStatic() ? IdKind.STATICMETHOD
				: IdKind.VIRTUALMETHOD;
	}


	/**
	 * @return the node in which is was declared
	 */
	public ASTNode getDeclNode() {
		return declNode;
	}

	/**
	 * @return the type
	 */
	public Type getType() {
		return type;
	}

	/**
	 * @return the kind
	 */
	public boolean isClass() 		{	return kind==IdKind.CLASS;				}
	public boolean isLocalVar() 	{	return kind==IdKind.LOCALVAR;			}
	public boolean isVirtualMethod(){	return kind==IdKind.VIRTUALMETHOD; 		}
	public boolean isFormalParam() 	{	return kind==IdKind.FORMALPARAM;		}
	public boolean isStaticMethod() {	return kind==IdKind.STATICMETHOD;		}
	public boolean isMemberVar() 	{	return kind==IdKind.MEMBERVAR;			}
	public boolean isVar() 			{	return IdKind.VarSet.contains(kind);	}
	public boolean isMethod() 		{	return IdKind.MethodSet.contains(kind);	}
	public boolean isReturnType()	{	return kind==IdKind.RETURNTYPE;			}
	public boolean isThis() 		{	return kind==IdKind.THIS;				}

	/**
	 * @return entry string
	 */
	public String toString() {
		return kind+"-"+type;
	}
}
